﻿using Parsers;
using ScreenCapture;
using TCPServer;

using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
using System.Drawing;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
using System.Diagnostics;

namespace Server
{
    public class RemoteServer : Servers
    {
        // create instances of different parsers
        MainParser mainParser = new MainParser("MainParser");
        ConsoleParser consoleParser = new ConsoleParser("ConsoleParser");
        ChatParser chatParser = new ChatParser("ChatParser");
        ScreenParser screenParser = new ScreenParser("ScreenParser");
        
        public RemoteServer() : base() { }
        public RemoteServer(int port): base(port){ }

        public override void Serve()
        {
            if (Running)
            {
                return;
            }
            else
            {
                Running = true;
            }
            
            EndPoint host = (EndPoint)new IPEndPoint(IPAddress.Any, Port); // get host end point | listen to all interfaces | Port: 55665
            Socket listener;
            listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            listener.Bind(host);    // bind to host
            listener.Listen(10);
            #region ServerLoop
            while (Running)
            {
                StringBuilder msg = new StringBuilder();
                try
                {
                    Socket conn = listener.Accept();
                    if (conn != null)
                    {

                        int read = 0;
                        string str = "";
                        do
                        {
                            byte[] buf = new byte[1024];
                            read = conn.Receive(buf);
                            str = Encoding.ASCII.GetString(buf).Trim('\n', '\r', '\0', '\t');
                            msg.Append(Encoding.ASCII.GetString(buf).Trim('\n', '\r', '\0', '\t'));
                            buf = null;
                            if (str.Contains("out"))
                            {
                                Console.WriteLine(msg.ToString());
                            }
                            if (str.Contains("hi!"))
                            {
                                conn.Send(Encoding.ASCII.GetBytes("\r\nHello L0n3w0lf :)\r\n"));
                            }
                        } while (read > 0 && !str.Contains("quit"));
                        Console.WriteLine("Msg: \n" + msg.ToString());
                        conn.Send(Encoding.ASCII.GetBytes("OK"));

                        CommandDescriptor MainCmdDesc = mainParser.Parse(msg.ToString());
                        if (MainCmdDesc.Command == "RemoteConsole")
                        {
                            CommandDescriptor consoleCmdDesc = consoleParser.Parse(MainCmdDesc.InnerData);
                        }
                        else if (MainCmdDesc.Command == "RemoteChat")
                        {
                            CommandDescriptor chatCmdDesc = chatParser.Parse(MainCmdDesc.InnerData);
                        }
                        else if (MainCmdDesc.Command == "RemoteScreen")
                        {
                            CommandDescriptor screenCmdDesc = screenParser.Parse(MainCmdDesc.InnerData);
                            Bitmap bmp = ScreenCapture.CaptureScreen.CaptureDesktopWithCursor();
                            BinaryFormatter bf = new BinaryFormatter();

                            MemoryStream ms = new MemoryStream();
                            bf.Serialize(ms, bmp);
                            byte[] buf = ms.GetBuffer();
                            conn.Send(buf);

                            // Experimental code
                            ms.Seek(0, SeekOrigin.Begin);
                            Bitmap bm = (Bitmap)bf.Deserialize(ms);
                            bm.Save("a.jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
                            ///////////////////////

                        }
                        Console.WriteLine("Type: " + MainCmdDesc.Command);
                        conn.Close();
                    }
                }
                catch (ThreadInterruptedException tex)
                {
                    tex.ToString();
                    break;  // stop thread
                }
                catch (ThreadAbortException tex)
                {
                    tex.ToString();
                    break;  // stop thread
                }
                catch (Exception ex)
                {
                    ex.ToString();  //do something
                }
                finally
                {
                    Debug.Fail("Closing");
                    listener.Shutdown(SocketShutdown.Both);
                }
            } 
            #endregion
        }
    }
}